"""
Built-in validate comparators.
"""
import re,allure,json
from .log import log
import pytest

def allure_attachment(raw,title):
    allure.attach(json.dumps(raw, ensure_ascii=False, indent=4),
        title,
        allure.attachment_type.JSON,
    )

def handle_exceptions( func):
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            msg = f'出错！（{e}）'
            log.error(msg)

    return wrapper

def equals(check_value, expect_value):
    #
    # check_value = None if check_value == 'None' else check_value   #None
    # expect_value = None if expect_value ==  'None' else expect_value

    result=check_value == expect_value
    raw={
        "预期结果": expect_value,
        "断言类型": "==",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)


    pytest.assume(check_value == expect_value , f'{check_value}->{type(check_value)} == {expect_value}->{type(expect_value)}')



def less_than(check_value, expect_value):
    result=check_value < expect_value
    raw={
        "预期结果": expect_value,
        "断言类型": "< ",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)


    pytest.assume(check_value < expect_value, f'{check_value} < {expect_value}')


def less_than_or_equals(check_value, expect_value):
    result=check_value <=  expect_value
    raw={
        "预期结果": expect_value,
        "断言类型": "<=",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(check_value <= expect_value, f'{check_value} <= {expect_value}')


def greater_than(check_value, expect_value):
    result=check_value > expect_value
    raw={
        "预期结果": expect_value,
        "断言类型": ">",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)
    pytest.assume(check_value > expect_value, f'{check_value} > {expect_value}')


def greater_than_or_equals(check_value, expect_value):
    result=check_value >= expect_value
    raw={
        "预期结果": expect_value,
        "断言类型": ">=",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)
    pytest.assume(check_value >= expect_value, f'{check_value} >= {expect_value}')


def not_equals(check_value, expect_value):
    result=check_value != expect_value
    raw={
        "预期结果": expect_value,
        "断言类型": "!=",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(check_value != expect_value, f'{check_value} != {expect_value}')


def string_equals(check_value, expect_value):
    result=str(check_value) == str(expect_value)
    raw={
        "预期结果": expect_value,
        "断言类型": "==",
        "实际结果": check_value,
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(str(check_value) == str(expect_value), f'{check_value} == {expect_value}')


def length_equals(check_value, expect_value):
    expect_len = _cast_to_int(expect_value)

    result = len(str(check_value)) ==expect_len
    raw = {
        "预期结果": f'预期长度：{expect_len}',
        "断言类型": "实际长度 == 预期长度",
        "实际结果": f'实际长度：{len(str(check_value))}',
        "测试结果": result
    }
    title = f'断言：{result}'
    allure_attachment(raw, title)

    if isinstance(check_value, list):

        pytest.assume(len(check_value) == expect_len, f'{len(check_value)} == {expect_value}')
    elif isinstance(check_value, (int, float)):
        pytest.assume(len(str(check_value)) == expect_len, f'{len(str(check_value))} == {expect_value}')
    else:
        pytest.assume(len(check_value) == expect_len, f'{len(check_value)} == {expect_value}')


def length_greater_than(check_value, expect_value):

    expect_len = _cast_to_int(expect_value)

    result=len(check_value) > expect_len
    raw={
        "预期结果": f'预期长度：{expect_len}',
        "断言类型": "实际长度 > 预期长度",
        "实际结果": f'实际长度：{len(check_value)}',
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(len(check_value) > expect_len, f'{len(check_value)} > {expect_value}')


def length_greater_than_or_equals(check_value, expect_value):
    expect_len = _cast_to_int(expect_value)

    result=len(check_value) >= expect_len
    raw={
        "预期结果": f'预期长度：{expect_len}',
        "断言类型": "实际长度 >= 预期长度",
        "实际结果": f'实际长度：{len(check_value)}',
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(len(check_value) >= expect_len, f'{len(check_value)} >= {expect_value}')


def length_less_than(check_value, expect_value):
    expect_len = _cast_to_int(expect_value)

    result=len(check_value) < expect_len
    raw={
        "预期结果": f'预期长度：{expect_len}',
        "断言类型": "实际长度 < 预期长度",
        "实际结果": f'实际长度：{len(check_value)}',
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(len(check_value) < expect_len, f'{len(check_value)} < {expect_value}')


def length_less_than_or_equals(check_value, expect_value):
    expect_len = _cast_to_int(expect_value)

    result=len(check_value) <= expect_len
    raw={
        "预期结果": f'预期长度：{expect_len}',
        "断言类型": "实际长度 <= 预期长度",
        "实际结果": f'实际长度：{len(check_value)}',
        "测试结果": result
    }
    title=f'断言：{result}'
    allure_attachment(raw,title)

    pytest.assume(len(check_value) <= expect_len, f'{len(check_value)} <= {expect_value}')


def contains(check_value, expect_value):
    if isinstance(check_value, (list, tuple, dict, str)):
        result = expect_value in check_value
        raw = {
            "预期结果": expect_value,
            "断言类型": "预期长度 in 实际长度",
            "实际结果": check_value,
            "测试结果": result
        }
        title = f'断言：{result}'
        allure_attachment(raw, title)


        pytest.assume(expect_value in check_value, f'{expect_value} in {check_value}')
    else:
        # 数字类型包含

        result = expect_value in str(check_value)
        raw = {
            "预期结果": expect_value,
            "断言类型": "预期长度 in 实际长度",
            "实际结果": check_value,
            "测试结果": result
        }
        title = f'断言：{result}'
        allure_attachment(raw, title)


        pytest.assume(expect_value in str(check_value), f'{expect_value} in {check_value}')


def contained_by(check_value, expect_value):
    if isinstance(expect_value, (list, tuple, dict, str)):


        result = check_value in expect_value
        raw = {
            "预期结果": expect_value,
            "断言类型": "实际长度 in 预期长度",
            "实际结果": check_value,
            "测试结果": result
        }
        title = f'断言：{result}'
        allure_attachment(raw, title)

        pytest.assume(check_value in expect_value, f'{check_value} in {expect_value}')
    else:
        # 数字类型包含
        result = str(check_value) in expect_value
        raw = {
            "预期结果": expect_value,
            "断言类型": "实际长度 in 预期长度",
            "实际结果": check_value,
            "测试结果": result
        }
        title = f'断言：{result}'
        allure_attachment(raw, title)

        pytest.assume(str(check_value) in expect_value, f'{check_value} in {check_value}')


def regex_match(check_value, expect_value):


    pytest.assume(isinstance(expect_value, str))
    pytest.assume(isinstance(check_value, str))
    pytest.assume(re.match(expect_value, check_value))


def startswith(check_value, expect_value):
    pytest.assume(str(check_value).startswith(str(expect_value)), f'{str(check_value)} startswith {str(expect_value)}')


def endswith(check_value, expect_value):
    pytest.assume(str(check_value).endswith(str(expect_value)), f'{str(check_value)} endswith {str(expect_value)}')


def _cast_to_int(expect_value):
    try:
        return int(expect_value)
    except Exception:
        raise AssertionError(f"%{expect_value} can't cast to int")


def bool_equals(check_value, expect_value):
    pytest.assume(bool(check_value) == bool(expect_value), f'{check_value} -> {bool(check_value)} == {expect_value}')
